home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mint99s
/
fasttext.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-23
|
25KB
|
1,301 lines
/*
Copyright 1992,1992 Eric R. Smith.
Copyright 1992 Atari Corporation.
All rights reserved.
*/
#include "mint.h"
#include "fasttext.h"
#ifdef FASTTEXT
#ifdef __GNUC__
#define INLINE inline
#define ITYPE long /* gcc's optimizer likes 32 bit integers */
#else
#define INLINE
#define ITYPE int
#endif
#define CONDEV (2)
static SCREEN *current;
static void paint P_((SCREEN *, int, char *)),
paint8c P_((SCREEN *, int, char *)),
paint16m P_((SCREEN *, int, char *));
INLINE static void curs_off P_((SCREEN *)), curs_on P_((SCREEN *));
INLINE static void flash P_((SCREEN *));
static void normal_putch P_((SCREEN *, int));
static void escy_putch P_((SCREEN *, int));
static void quote_putch P_((SCREEN *, int));
static char *chartab[256];
#define MAX_PLANES 8
static int fgmask[MAX_PLANES], bgmask[MAX_PLANES];
static long scrnsize;
short hardscroll;
static char *hardbase, *oldbase;
typedef void (*Vfunc) P_((SCREEN *, int));
#define base *((char **)0x44eL)
#define escy1 *((short *)0x4acL)
static Vfunc state;
static short hardline;
static void (*vpaint) P_((SCREEN *, int, char *));
void init P_((void));
void hardware_scroll P_((SCREEN *));
INLINE static char *PLACE P_((SCREEN *, int, int));
INLINE static void gotoxy P_((SCREEN *, int, int));
INLINE static void clrline P_((SCREEN *, int));
INLINE static void clear P_((SCREEN *));
INLINE static void clrchar P_((SCREEN *, int, int));
INLINE static void clrfrom P_((SCREEN *, int, int, int, int));
INLINE static void delete_line P_((SCREEN *, int));
INLINE static void insert_line P_((SCREEN *, int));
static void setbgcol P_((SCREEN *, int));
static void setfgcol P_((SCREEN *, int));
static void putesc P_((SCREEN *, int));
static void escy1_putch P_((SCREEN *, int));
INLINE static void put_ch P_((SCREEN *, int));
/* routines for flashing the cursor for screen v */
/* flash(v): invert the character currently under the cursor */
INLINE static void
flash(v)
SCREEN *v;
{
char *place;
ITYPE i, j, vplanes;
vplanes = v->planes + v->planes;
place = v->cursaddr;
for (j = v->cheight; j > 0; --j) {
for (i = 0; i < vplanes; i+=2)
place[i] = ~place[i];
place += v->planesiz;
}
v->curstimer = v->period;
}
/* make sure the cursor is off */
INLINE
static void
curs_off(v)
SCREEN *v;
{
if (v->flags & CURS_ON) {
if (v->flags & CURS_FSTATE) {
flash(v);
v->flags &= ~CURS_FSTATE;
}
}
}
/* OK, show the cursor again (if appropriate) */
INLINE static void
curs_on(v)
SCREEN *v;
{
if (v->hidecnt) return;
if (v->flags & CURS_ON) {
#if 0
/* if the cursor is flashing, we cheat a little and leave it off
* to be turned on again (if necessary) by the VBL routine
*/
if (v->flags & CURS_FLASH) {
v->curstimer = 2;
return;
}
#endif
if (!(v->flags & CURS_FSTATE)) {
v->flags |= CURS_FSTATE;
flash(v);
}
}
}
void
init()
{
SCREEN *v;
int i, j;
char *data, *foo;
static char chardata[256*16];
foo = lineA0();
v = (SCREEN *)(foo - 346);
/* Ehem... The screen might be bigger than 32767 bytes.
Let's do some casting...
Erling
*/
scrnsize = (v->maxy+1)*(long)v->linelen;
if (hardscroll == -1) {
/* request for auto-setting */
hardscroll = v->maxy+1;
}
if (hardscroll > 0) {
if (!hardbase)
hardbase = (char *)(((long)kcore(SCNSIZE(v)+256L)+255L)
& 0xffffff00L);
if (hardbase == 0) {
ALERT("Insufficient memory for hardware scrolling!");
} else {
quickmove(hardbase, base, scrnsize);
v->cursaddr = v->cursaddr + (hardbase - base);
oldbase = base;
base = hardbase;
Setscreen(hardbase, hardbase, -1);
}
}
hardline = 0;
if (v->cheight == 8 && v->planes == 2) {
foo = &chardata[0];
vpaint = paint8c;
for (i = 0; i < 256; i++) {
chartab[i] = foo;
data = v->fontdata + i;
for (j = 0; j < 8; j++) {
*foo++ = *data;
data += v->form_width;
}
}
} else if (v->cheight == 16 && v->planes == 1) {
foo = &chardata[0];
vpaint = paint16m;
for (i = 0; i < 256; i++) {
chartab[i] = foo;
data = v->fontdata + i;
for (j = 0; j < 16; j++) {
*foo++ = *data;
data += v->form_width;
}
}
}
else
vpaint = paint;
if (v->hidecnt == 0) {
/*
* make sure the cursor is set up correctly and turned on
*/
(void)Cursconf(0,0); /* turn cursor off */
v->flags &= ~CURS_FSTATE;
/* now turn the cursor on the way we like it */
v->hidecnt = 0;
curs_on(v);
} else {
(void)Cursconf(0,0);
v->flags &= ~CURS_ON;
v->hidecnt = 1;
}
current = v;
/* setup bgmask and fgmask */
setbgcol(v, v->bgcol);
setfgcol(v, v->fgcol);
state = normal_putch;
}
/*
* PLACE(v, x, y): the address corresponding to the upper left hand corner of
* the character at position (x,y) on screen v
*/
INLINE static
char *PLACE(v, x, y)
SCREEN *v;
int x, y;
{
char *place;
int i, j;
place = base + x;
if (y == v->maxy)
place += scrnsize - v->linelen;
else if (y) /* Yo, the screen might be bigger than 32767 bytes...
Do a cast to long. Erling. */
place += (long)y * v->linelen;
if ((j = v->planes) > 1) {
i = (x & 0xfffe);
while (--j > 0)
place += i;
}
return place;
}
/*
* paint(v, c, place): put character 'c' at position 'place' on screen
* v. It is assumed that x, y are proper coordinates!
* Specialized versions (paint8c and paint16m) of this routine follow;
* they assume 8 line high characters, medium res. and 16 line/mono,
* respectively.
*/
static void
paint(v, c, place)
SCREEN *v;
int c;
char *place;
{
char *data, d, doinverse;
ITYPE j, planecount;
int vplanes;
long vform_width, vplanesiz;
vplanes = v->planes;
data = v->fontdata + c;
doinverse = (v->flags & FINVERSE) ? 0xff : 0;
vform_width = v->form_width;
vplanesiz = v->planesiz;
for (j = v->cheight; j > 0; --j) {
d = *data ^ doinverse;
for (planecount = 0; planecount < vplanes; planecount++)
place[planecount << 1]
= ((d & (char) fgmask[planecount])
| (~d & (char) bgmask[planecount]));
place += vplanesiz;
data += vform_width;
}
}
static void
paint8c(v, c, place)
SCREEN *v;
int c;
char *place;
{
char *data;
char d, doinverse;
char bg0, bg1, fg0, fg1;
long vplanesiz;
data = chartab[c];
doinverse = (v->flags & FINVERSE) ? 0xff : 0;
vplanesiz = v->planesiz;
bg0 = bgmask[0];
bg1 = bgmask[1];
fg0 = fgmask[0];
fg1 = fgmask[1];
if (!doinverse && !bg0 && !bg1 && fg0 && fg1) {
/* line 1 */
d = *data++;
*place = d;
place[2] = d;
place += vplanesiz;
/* line 2 */
d = *data++;
*place = d;
place[2] = d;
place += vplanesiz;
/* line 3 */
d = *data++;
*place = d;
place[2] = d;
place += vplanesiz;
/* line 4 */
d = *data++;
*place = d;
place[2] = d;
place += vplanesiz;
/* line 5 */
d = *data++;
*place = d;
place[2] = d;
place += vplanesiz;
/* line 6 */
d = *data++;
*place = d;
place[2] = d;
place += vplanesiz;
/* line 7 */
d = *data++;
*place = d;
place[2] = d;
place += vplanesiz;
/* line 8 */
d = *data;
*place = d;
place[2] = d;
} else {
/* line 1 */
d = *data++ ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
place += vplanesiz;
/* line 2 */
d = *data++ ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
place += vplanesiz;
/* line 3 */
d = *data++ ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
place += vplanesiz;
/* line 4 */
d = *data++ ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
place += vplanesiz;
/* line 5 */
d = *data++ ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
place += vplanesiz;
/* line 6 */
d = *data++ ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
place += vplanesiz;
/* line 7 */
d = *data++ ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
place += vplanesiz;
/* line 8 */
d = *data ^ doinverse;
*place = ((d & fg0) | (~d & bg0));
place[2] = ((d & fg1) | (~d & bg1));
}
}
static void
paint16m(v, c, place)
SCREEN *v;
int c;
char *place;
{
char *data;
char d, doinverse;
long vplanesiz;
data = chartab[c];
doinverse = (v->flags & FINVERSE) ? 0xff : 0;
doinverse ^= bgmask[0];
vplanesiz = v->planesiz;
if (bgmask[0] == fgmask[0])
{
/* fgcol and bgcol are the same -- easy */
d = (char) bgmask[0];
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
place += vplanesiz;
*place = d;
}
else if (!doinverse) {
/* line 1 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 2 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 3 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 4 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 5 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 6 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 7 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 8 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 9 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 10 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 11 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 12 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 13 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 14 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 15 */
d = *data++;
*place = d;
place += vplanesiz;
/* line 16 */
d = *data;
*place = d;
} else {
/* line 1 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 2 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 3 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 4 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 5 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 6 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 7 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 8 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 9 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 10 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 11 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 12 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 13 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 14 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 15 */
d = ~*data++;
*place = d;
place += vplanesiz;
/* line 16 */
d = ~*data;
*place = d;
}
}
/*
* gotoxy (v, x, y): move current cursor address of screen v to (x, y)
* makes sure that (x, y) will be legal
*/
INLINE static void
gotoxy(v, x, y)
SCREEN *v;
int x, y;
{
if (x > v->maxx) x = v->maxx;
else if (x < 0) x = 0;
if (y > v->maxy) y = v->maxy;
else if (y < 0) y = 0;
v->cx = x;
v->cy = y;
v->cursaddr = PLACE(v, x, y);
}
/*
* clrline(v, r): clear line r of screen v
*/
INLINE static void
clrline(v, r)
SCREEN *v;
int r;
{
int *dst, *m;
long nwords;
int i, vplanes;
/* Hey, again the screen might be bigger than 32767 bytes.
Do another cast... */
dst = (int *)(base + ((long)r * v->linelen));
if (v->bgcol == 0)
zero((char *)dst, v->linelen);
else
{
/* do it the hard way */
vplanes = v->planes;
for (nwords = v->linelen >> 1; nwords > 0; nwords -= vplanes)
{
m = bgmask;
for (i = 0; i < vplanes; i++)
*dst++ = *m++;
}
}
}
/*
* clear(v): clear the whole screen v
*/
INLINE static void
clear(v)
SCREEN *v;
{
int i, vplanes;
int *dst, *m;
long nwords;
if (v->bgcol == 0)
zero(base, scrnsize);
else
{
/* do it the hard way */
dst = (int *) base;
vplanes = v->planes;
for (nwords = scrnsize >> 1; nwords > 0; nwords -= vplanes)
{
m = bgmask;
for (i = 0; i < vplanes; i++)
*dst++ = *m++;
}
}
}
/*
* clrchar(v, x, y): clear the (x,y) position on screen v
*/
INLINE static void
clrchar(v, x, y)
SCREEN *v;
int x, y;
{
int i, j, vplanes;
char *place;
int *m;
vplanes = v->planes + v->planes;
place = PLACE(v, x, y);
for (j = v->cheight; j > 0; --j) {
m = bgmask;
for (i = 0; i < vplanes; i += 2)
place[i] = (char) *m++;
place += v->planesiz;
}
}
/*
* clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
* position (x2, y2) inclusive. It is assumed that y2 >= y1.
*/
INLINE static void
clrfrom(v, x1, y1, x2, y2)
SCREEN *v;
int x1,y1,x2,y2;
{
int i;
for (i = x1; i <= v->maxx; i++)
clrchar(v, i, y1);
if (y2 > y1) {
for (i = 0; i <= x2; i++)
clrchar(v, i, y2);
for (i = y1+1; i < y2; i++)
clrline(v, i);
}
}
/*
* scroll a screen in hardware; if we still have hardware scrolling lines left,
* just move the physical screen base, otherwise copy the screen back to the
* hardware base and start over
*/
void
hardware_scroll(v)
SCREEN *v;
{
++hardline;
if (hardline < hardscroll) { /* just move the screen */
base += v->linelen;
v->cursaddr = PLACE(v, v->cx, v->cy);
Setscreen(base, base, -1);
}
else {
hardline = 0;
quickmove(hardbase, base + v->linelen, scrnsize - v->linelen);
base = hardbase;
v->cursaddr = PLACE(v, v->cx, v->cy);
Setscreen(hardbase, hardbase, -1);
}
}
/*
* delete_line(v, r): delete line r of screen v. The screen below this
* line is scrolled up, and the bottom line is cleared.
*/
#define scroll(v) delete_line(v, 0)
INLINE static void
delete_line(v, r)
SCREEN *v;
int r;
{
long *src, *dst, nbytes;
if (r == 0) {
if (hardbase) {
hardware_scroll(v);
clrline(v, v->maxy);
return;
}
nbytes = scrnsize - v->linelen;
}
else
nbytes = (long)v->linelen * (v->maxy - r);
/* Sheeze, how many times do we really have to cast...
Erling.
*/
dst = (long *)(base + ((long)r * v->linelen));
src = (long *)( ((long)dst) + v->linelen);
quickmove(dst, src, nbytes);
/* clear the last line */
clrline(v, v->maxy);
}
/*
* insert_line(v, r): scroll all of the screen starting at line r down,
* and then clear line r.
*/
INLINE static void
insert_line(v, r)
SCREEN *v;
int r;
{
long *src, *dst;
int i, limit;
limit = v->maxy;
for (i = limit-1; i >= r ; --i) {
/* move line i to line i+1 */
/* AND do some casting to support big screens.
Erling
*/
src = (long *)(base + ((long)i * v->linelen));
dst = (long *)(base + ((i+1)*(long)v->linelen));
quickmove(dst, src, v->linelen);
}
/* clear line r */
clrline(v, r);
}
/*
* special states for handling ESC b x and ESC c x. Note that for now,
* color is ignored.
*/
static void
setbgcol(v, c)
SCREEN *v;
int c;
{
int i;
v->bgcol = c & ((1 << v->planes)-1);
for (i = 0; i < v->planes; i++)
bgmask[i] = (v->bgcol & (1 << i)) ? -1 : 0;
state = normal_putch;
}
static void
setfgcol(v, c)
SCREEN *v;
int c;
{
int i;
v->fgcol = c & ((1 << v->planes)-1);
for (i = 0; i < v->planes; i++)
fgmask[i] = (v->fgcol & (1 << i)) ? -1 : 0;
state = normal_putch;
}
static void
quote_putch(v, c)
SCREEN *v;
int c;
{
(*vpaint)(v, c, v->cursaddr);
state = normal_putch;
v->cx++;
if (v->cx > v->maxx) {
if (v->flags & FWRAP) {
v->cx = 0;
normal_putch(v, '\n');
v->cursaddr = PLACE(v, v->cx, v->cy);
} else {
v->cx = v->maxx;
}
} else {
#if 0
v->cursaddr = PLACE(v, v->cx, v->cy);
#else
v->cursaddr++;
if ( (v->cx & 1) == 0 && v->planes > 1) { /* new word */
short skipwords = v->planes - 1;
v->cursaddr += skipwords+skipwords;
}
#endif
}
}
/*
* putesc(v, c): handle the control sequence ESC c
*/
static void
putesc(v, c)
SCREEN *v;
int c;
{
int cx, cy;
cx = v->cx; cy = v->cy;
switch (c) {
case 'A': /* cursor up */
gotoxy(v, cx, cy-1);
break;
case 'B': /* cursor down */
gotoxy(v, cx, cy+1);
break;
case 'C': /* cursor right */
gotoxy(v, cx+1, cy);
break;
case 'D': /* cursor left */
gotoxy(v, cx-1, cy);
break;
case 'E': /* clear home */
clear(v);
/* fall through... */
case 'H': /* cursor home */
gotoxy(v, 0, 0);
break;
case 'I': /* cursor up, insert line */
if (cy == 0) {
insert_line(v, 0);
}
else
gotoxy(v, cx, cy-1);
break;
case 'J': /* clear below cursor */
clrfrom(v, cx, cy, v->maxx, v->maxy);
break;
case 'K': /* clear remainder of line */
clrfrom(v, cx, cy, v->maxx, cy);
break;
case 'L': /* insert a line */
gotoxy(v, 0, cy);
insert_line(v, cy);
break;
case 'M': /* delete line */
gotoxy(v, 0, cy);
delete_line(v, cy);
break;
case 'Q': /* quote-next-char */
state = quote_putch;
return;
case 'Y':
state = escy_putch;
return; /* YES, this should be 'return' */
case 'b':
state = setfgcol;
return;
case 'c':
state = setbgcol;
return;
case 'd': /* clear to cursor position */
clrfrom(v, 0, 0, cx, cy);
break;
case 'e': /* enable cursor */
v->flags |= CURS_ON;
v->hidecnt = 1; /* so --v->hidecnt shows the cursor */
break;
case 'f': /* cursor off */
v->hidecnt++;
v->flags &= ~CURS_ON;
break;
case 'j': /* save cursor position */
v->savex = v->cx;
v->savey = v->cy;
break;
case 'k': /* restore saved position */
gotoxy(v, v->savex, v->savey);
break;
case 'l': /* clear line */
gotoxy(v, 0, cy);
clrline(v, cy);
break;
case 'o': /* clear from start of line to cursor */
clrfrom(v, 0, cy, cx, cy);
break;
case 'p': /* reverse video on */
v->flags |= FINVERSE;
break;
case 'q': /* reverse video off */
v->flags &= ~FINVERSE;
break;
case 'v': /* wrap on */
v->flags |= FWRAP;
break;
case 'w':
v->flags &= ~FWRAP;
break;
}
state = normal_putch;
}
/*
* escy1_putch(v, c): for when an ESC Y + char has been seen
*/
static void
escy1_putch(v, c)
SCREEN *v;
int c;
{
gotoxy(v, c - ' ', escy1 - ' ');
state = normal_putch;
}
/*
* escy_putch(v, c): for when an ESC Y has been seen
*/
static void
escy_putch(v, c)
SCREEN *v;
int c;
{
UNUSED(v);
escy1 = c;
state = escy1_putch;
}
/*
* normal_putch(v, c): put character 'c' on screen 'v'. This is the default
* for when no escape, etc. is active
*/
static void
normal_putch(v, c)
SCREEN *v;
int c;
{
/* control characters */
if (c < ' ') {
switch (c) {
case '\r':
gotoxy(v, 0, v->cy);
return;
case '\n':
if (v->cy == v->maxy) {
scroll(v);
}
else
gotoxy(v, v->cx, v->cy+1);
return;
case '\b':
gotoxy(v, v->cx-1, v->cy);
return;
case '\007': /* BELL */
(void)bconout(CONDEV, 7);
return;
case '\033': /* ESC */
state = putesc;
return;
case '\t':
gotoxy(v, (v->cx + 8) & ~7, v->cy);
return;
default:
return;
}
}
(*vpaint)(v, c, v->cursaddr);
v->cx++;
if (v->cx > v->maxx) {
if (v->flags & FWRAP) {
v->cx = 0;
normal_putch(v, '\n');
v->cursaddr = PLACE(v, v->cx, v->cy);
} else {
v->cx = v->maxx;
}
} else {
#if 0
v->cursaddr = PLACE(v, v->cx, v->cy);
#else
v->cursaddr++;
if ( (v->cx & 1) == 0 && v->planes > 1) { /* new word */
short skipwords = v->planes - 1;
v->cursaddr += skipwords+skipwords;
}
#endif
}
}
INLINE static void
put_ch(v, c)
SCREEN *v;
int c;
{
(*state)(v, c & 0x00ff);
}
static long ARGS_ON_STACK screen_open P_((FILEPTR *f));
static long ARGS_ON_STACK screen_read P_((FILEPTR *f, char *buf, long nbytes));
static long ARGS_ON_STACK screen_write P_((FILEPTR *f, const char *buf, long nbytes));
static long ARGS_ON_STACK screen_lseek P_((FILEPTR *f, long where, int whence));
static long ARGS_ON_STACK screen_ioctl P_((FILEPTR *f, int mode, void *buf));
static long ARGS_ON_STACK screen_close P_((FILEPTR *f, int pid));
static long ARGS_ON_STACK screen_select P_((FILEPTR *f, long p, int mode));
static void ARGS_ON_STACK screen_unselect P_((FILEPTR *f, long p, int mode));
extern long ARGS_ON_STACK null_datime P_((FILEPTR *f, short *time, int rwflag));
DEVDRV screen_device = {
screen_open, screen_write, screen_read, screen_lseek, screen_ioctl,
null_datime, screen_close, screen_select, screen_unselect
};
static long ARGS_ON_STACK
screen_open(f)
FILEPTR *f;
{
if (!current) {
init();
} else
return EACCDN; /* screen in use */
f->flags |= O_TTY;
return 0;
}
static long ARGS_ON_STACK
screen_close(f, pid)
FILEPTR *f;
int pid;
{
UNUSED(pid);
if (f->links <= 0) {
if (hardbase) {
quickmove(oldbase, base, scrnsize);
base = oldbase;
Setscreen(oldbase, oldbase, -1);
}
current = 0;
}
return 0;
}
static long ARGS_ON_STACK
screen_write(f, buf, bytes)
FILEPTR *f; const char *buf; long bytes;
{
SCREEN *v = current;
long *r;
long ret = 0;
int c;
UNUSED(f);
(void)checkkeys();
v->hidecnt++;
v->flags |= CURS_UPD; /* for TOS 1.0 */
curs_off(v);
r = (long *)buf;
while (bytes > 0) {
c = (int) *r++;
put_ch(v, c);
bytes -= 4; ret+= 4;
}
if (v->hidecnt > 0)
--v->hidecnt;
else
v->hidecnt = 0;
curs_on(v);
v->flags &= ~CURS_UPD;
return ret;
}
static long ARGS_ON_STACK
screen_read(f, buf, bytes)
FILEPTR *f; char *buf; long bytes;
{
long *r, ret = 0;
r = (long *)buf;
while (bytes > 0) {
if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
break;
*r++ = bconin(CONDEV) & 0x7fffffffL;
bytes -= 4; ret += 4;
}
return ret;
}
static long ARGS_ON_STACK
screen_lseek(f, where, whence)
FILEPTR *f;
long where;
int whence;
{
/* terminals always are at position 0 */
UNUSED(f); UNUSED(where);
UNUSED(whence);
return 0;
}
static long ARGS_ON_STACK
screen_ioctl(f, mode, buf)
FILEPTR *f; int mode; void *buf;
{
long *r = (long *)buf;
struct winsize *w;
UNUSED(f);
if (mode == FIONREAD) {
if (bconstat(CONDEV))
*r = 1;
else
*r = 0;
}
else if (mode == FIONWRITE) {
*r = 1;
}
else if (mode == TIOCFLUSH) {
/* BUG: this should flush the input/output buffers */
return 0;
}
else if (mode == TIOCGWINSZ) {
w = (struct winsize *)buf;
w->ws_row = current->maxy+1;
w->ws_col = current->maxx+1;
}
else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
SCREEN *v = current;
switch(mode) {
case TCURSOFF:
curs_off(v);
v->hidecnt++;
v->flags &= ~CURS_ON;
break;
case TCURSON:
v->flags |= CURS_ON;
v->hidecnt = 0;
curs_on(v);
break;
case TCURSBLINK:
curs_off(v);
v->flags |= CURS_FLASH;
curs_on(v);
break;
case TCURSSTEADY:
curs_off(v);
v->flags &= ~CURS_FLASH;
curs_on(v);
break;
case TCURSSRATE:
v->period = *((short *)buf);
break;
case TCURSGRATE:
return v->period;
}
} else
return EINVFN;
return 0;
}
static long ARGS_ON_STACK
screen_select(f, p, mode)
FILEPTR *f; long p; int mode;
{
struct tty *tty = (struct tty *)f->devinfo;
int dev = CONDEV;
if (mode == O_RDONLY) {
if (bconstat(dev)) {
return 1;
}
if (tty) {
/* avoid collisions with other processes */
if (!tty->rsel)
tty->rsel = p;
}
return 0;
} else if (mode == O_WRONLY) {
return 1;
}
/* default -- we don't know this mode, return 0 */
return 0;
}
static void ARGS_ON_STACK
screen_unselect(f, p, mode)
FILEPTR *f;
long p;
int mode;
{
struct tty *tty = (struct tty *)f->devinfo;
if (tty) {
if (mode == O_RDONLY && tty->rsel == p)
tty->rsel = 0;
else if (mode == O_WRONLY && tty->wsel == p)
tty->wsel = 0;
}
}
#endif /* FASTTEXT */